package com.jingdianjichi.gateway.exception;

import cn.dev33.satoken.exception.SaTokenException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jingdianjichi.gateway.entity.Result;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * ClassName :GatewayExceptionHandler
 * Package :com.jingdianjichi.gateway.exception
 * Desciption :
 *
 * @Author :
 * @Create : 23:15
 * @Version :1.0
 */
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
    private ObjectMapper objectMapper = new ObjectMapper();//将自定义的类序列化为json

    @Override
    public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
        ServerHttpRequest request = serverWebExchange.getRequest();
        ServerHttpResponse response = serverWebExchange.getResponse();
        //serverWebExchange这个参数里面包含了request和response
        //throwable里面包含了捕获的所有异常
        Integer code = 200;
        String message = "";
        if (throwable instanceof SaTokenException) {
            code = 401;
            message = "用户无权限";
            throwable.printStackTrace();
        } else {
            code = 500;
            message = "系统繁忙";
            throwable.printStackTrace();
        }
        Result result = Result.fail(code, message);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);//设置响应投返回的数据为json串
        return response.writeWith(Mono.fromSupplier(() -> {//向响应体里面塞数据
            DataBufferFactory dataBufferFactory = response.bufferFactory();
//            1. DataBuffer 的作用
//            DataBuffer 是 Spring WebFlux 中用于表示数据缓冲区的接口，它封装了字节数据，并提供了一些操作字节数据的方法。DataBuffer 的主要用途包括：
//            存储和操作字节数据：可以用于存储响应体中的数据，例如 JSON 字符串的字节表示。
//            支持异步和非阻塞操作：在异步编程中，DataBuffer 可以高效地处理数据流，而不会阻塞线程。
//            2. DataBufferFactory 的作用
//            DataBufferFactory 是一个工厂类，用于创建 DataBuffer 对象。它提供了多种方法来创建不同类型的 DataBuffer，例如：
//            wrap(byte[] bytes)：将字节数组包装成一个 DataBuffer。
//            wrap(ByteBuffer byteBuffer)：将 ByteBuffer 包装成一个 DataBuffer。
//            wrap(ByteBuffer... byteBuffers)：将多个 ByteBuffer 包装成一个 DataBuffer。
//            allocateBuffer()：分配一个新的 DataBuffer。
//            allocateBuffer(int initialCapacity)：分配一个指定初始容量的 DataBuffer。

            byte[] bytes = null;
            try {
                bytes = objectMapper.writeValueAsBytes(result);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return dataBufferFactory.wrap(bytes);//这一步配合 response.getHeaders().setContentType(MediaType.APPLICATION_JSON);就可以将result当作
            //json串返回
        }));
    }
}
